package com.example.shop.rabbitmq.component;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;

@Configuration
public class OrderComponents {

    /**
     * 订单的交换机
     */
    public static final String ORDER_EXCHANGE = "order.direct";
    /**
     * 订单的死信交换机
     */
    public static final String ORDER_DEAD_EXCHANGE = "order.direct.dead";


//=========================================||  未支付订单  ||====================================================
    /**
     * 未支付队列的路由key键
     */
    public static final String NO_PAY_ROUTING_KEY = "NoPayRoutingKey";

    /**
     * 未支付订单的队列
     */
    public static final String NO_PAY_QUEUE = "order_noPay_queue";

    /**
     * 未支付订单的死信队列
     */
    public static final String NO_PAY_DEAD_QUEUE = "order_noPay_deadQueue";

    /**
     * 声明一个订单的交换机
     * @return 返回一个Direct路由交换机
     */
    @Bean
    public DirectExchange orderExchange(){
        //声明一个Direct路由交换机，交换机名为NO_PAY_EXCHANGE
        return ExchangeBuilder.directExchange(ORDER_EXCHANGE)
                //设置该交换机的持久性配置参数为持久化
                .durable(true)
                //设置备用交换机
//                .alternate()
                .build();
    }

    /**
     * 声明一个未支付订单的队列
     * @return 返回一个未支付订单的队列
     */
    @Bean
    public Queue noPayQueue(){
        HashMap<String, Object> queueProperties = new HashMap<>();
        //该队列里的所有消息的过期时间为30分钟
        queueProperties.put("x-message-ttl",1800000);
        //设置该队列超过该队列长度后，后来的信息都进入死信队列里。默认是覆盖前面的
        queueProperties.put("x-overflow","reject-publish-dlx");
        //队列在被自动删除之前可以使用30s,一旦设置，不管有没有设置自动删除，只要空闲30s后，自动删除
//        queueProperties.put("x-expires",30000);
        //设置该队列消费时，可以多个消费者，而不被单独一个消费者独占消费
        queueProperties.put("x-single-active-consumer",false);
        //设置该队列有死信交换机和死信队列
        queueProperties.put("x-dead-letter-exchange", ORDER_DEAD_EXCHANGE);
        //指定死信路由键前，要先指定死信交换机，死信路由键不设置，则默认为"";
        queueProperties.put("x-dead-letter-routing-key", NO_PAY_ROUTING_KEY);
        //队列模式为为lazy惰性模式(即在磁盘上保留尽可能多的消息以减少RAM的使用，如果没有设置，队列将保持内存缓存，以尽可能快地传递消息，但容易丢失消息)
        queueProperties.put("x-queue-mode", "lazy");
        //durable:持久化(true),exclusive：消费者不独占队列(true),autoDelete:不自动删除队列(false),arguments:队列配置参数(queueProperties)
        return new Queue(NO_PAY_QUEUE,true,false,false,queueProperties);
    }

    /**
     * 将订单的交换机和队列绑定在一起，绑定的键名为NO_PAY_ROUTING_KEY
     * @param orderExchange 订单的交换机
     * @param noPayQueue 未支付订单的队列
     * @return 返回绑定对象Binding
     */
    @Bean
    public Binding noPayBinding(DirectExchange orderExchange,Queue noPayQueue){
        return BindingBuilder.bind(noPayQueue).to(orderExchange).with(NO_PAY_ROUTING_KEY);
    }

    /**
     * 声明一个死信交换机
     * @return 返回一个死信交换机
     */
    @Bean
    public DirectExchange orderDeadExchange(){
        return ExchangeBuilder.directExchange(ORDER_DEAD_EXCHANGE)
                .durable(true)
                .build();
    }

    /**
     * 声明一个死信队列
     * @return 返回一个死信队列
     */
    @Bean
    public Queue noPayDeadQueue(){
        HashMap<String, Object> queueProperties = new HashMap<>();
        queueProperties.put("x-single-active-consumer",false);
        return new Queue(NO_PAY_DEAD_QUEUE,true,false,false,queueProperties);
    }

    /**
     * 将死信交换机和死信队列绑定在一起，绑定的键名为NO_PAY_ROUTING_KEY
     * @param orderDeadExchange 订单的死信交换机
     * @param noPayDeadQueue 死信队列
     * @return 返回绑定对象Binding
     */
    @Bean
    public Binding noPayDeadBinding(DirectExchange orderDeadExchange,Queue noPayDeadQueue){
        return BindingBuilder.bind(noPayDeadQueue).to(orderDeadExchange).with(NO_PAY_ROUTING_KEY);
    }

//========================================|| 待评价订单 ||====================================
    /**
     * 评价队列的路由key键
     */
    public static final String EVALUATE_ROUTING_KEY = "EvaluateRoutingKey";

    /**
     * 待评价的订单的队列
     */
    public static final String EVALUATE_QUEUE = "order_evaluate_queue";


    /**
     * 待评价的订单的死信队列
     */
    public static final String EVALUATE_DEAD_QUEUE = "order_evaluate_deadQueue";

    /**
     * 声明一个待评价的订单的队列
     * @return 返回一个待评价的订单的队列
     */
    @Bean
    public Queue evaluateQueue(){
        HashMap<String, Object> queueProperties = new HashMap<>();
        //该队列里的所有消息的过期时间为15天，如果15天内没有进行评论，则自动进行评论
        queueProperties.put("x-message-ttl",1296000000);
        //设置该队列消费时，可以多个消费者，而不被单独一个消费者独占消费
        queueProperties.put("x-single-active-consumer",true);
        //设置该队列有死信交换机和死信队列
        queueProperties.put("x-dead-letter-exchange", ORDER_DEAD_EXCHANGE);
        //指定死信路由键前，要先指定死信交换机，死信路由键不设置，则默认为"";
        queueProperties.put("x-dead-letter-routing-key", EVALUATE_ROUTING_KEY);
        //队列模式为为lazy惰性模式(即在磁盘上保留尽可能多的消息以减少RAM的使用，如果没有设置，队列将保持内存缓存，以尽可能快地传递消息，但容易丢失消息)
        queueProperties.put("x-queue-mode", "lazy");
        //durable:持久化(true),exclusive：消费者不独占队列(true),autoDelete:不自动删除队列(false),arguments:队列配置参数(queueProperties)
        return new Queue(EVALUATE_QUEUE,true,false,false,queueProperties);
    }

    /**
     * 将待评价的订单的交换机和队列绑定在一起，绑定的键名为EVALUATE_ROUTING_KEY
     * @param orderExchange 订单的交换机
     * @param evaluateQueue 待评价的订单的队列
     * @return 返回绑定对象Binding
     */
    @Bean
    public Binding evaluateBinding(DirectExchange orderExchange,Queue evaluateQueue){
        return BindingBuilder.bind(evaluateQueue).to(orderExchange).with(EVALUATE_ROUTING_KEY);
    }

    /**
     * 声明一个待评价订单的死信队列
     * @return 返回一个待评价订单的死信队列
     */
    @Bean
    public Queue evaluateDeadQueue(){
        HashMap<String, Object> queueProperties = new HashMap<>();
        queueProperties.put("x-single-active-consumer",false);
        return new Queue(EVALUATE_DEAD_QUEUE,true,false,false,queueProperties);
    }

    /**
     * 将死信交换机和死信队列绑定在一起，绑定的键名为EVALUATE_ROUTING_KEY
     * @param orderDeadExchange 订单的死信交换机
     * @param evaluateDeadQueue 待评价订单的死信队列
     * @return 返回绑定对象Binding
     */
    @Bean
    public Binding evaluateDeadBinding(DirectExchange orderDeadExchange,Queue evaluateDeadQueue){
        return BindingBuilder.bind(evaluateDeadQueue).to(orderDeadExchange).with(EVALUATE_ROUTING_KEY);
    }
}
